#ifndef ___fuse_truncate
#define ___fuse_truncate 1

#ifndef FUSE_USE_VERSION
#define FUSE_USE_VERSION 28
#endif

#include <stdio.h>
#include <stdlib.h>
#include "mtlib.c"
#include <fuse.h>
#include <fcntl.h>
#include <errno.h>
#include "logging.c"

struct datosTruncar {
    char * path;
    long pos;
    char estado;
};

//PROTOTIPOS
int fuse_truncate(const char *, off_t);
void ___fuse_procesar_mensaje_truncate(unsigned char, mti_mensaje, struct datosTruncar *);


//TRUNCAR ARCHIVO
int fuse_truncate(const char * path, off_t offset) { //cambia el tamaÃ±o de un archivo

    int resultado;
    mti_mensaje datosMensaje;
    struct datosTruncar datos;
    unsigned int descriptorConexion;
    unsigned char centro_truncate = 0;

        datos.estado = 0;
        datos.pos = (long)offset;
        datos.path = path;

        while(centro_truncate == 0)

            centro_truncate = mtf_obtener_descriptor(1024);

        descriptorConexion = mtf_conectar(centro_truncate, MTP_INTERNO, centro_fat);

        if (descriptorConexion == 0) {
            mtf_liberar_descriptor(centro_truncate); //libero centro de mensajes con sus datos y conexiones
            return -EAGAIN;

        } else

            //le mando un mensaje al sistema fat con el descriptor del archivo a truncar y la posicion a trucar
            resultado = mtf_enviar_mensaje(centro_truncate, descriptorConexion, MTE_TRUNCAR_ARCHIVO, (char *) datos.path,
                                            (long) datos.pos);

            if (resultado == 0) {
                mtf_desconectar(centro_truncate,descriptorConexion); //desconecto la conexion del centro de mensajes
                mtf_liberar_descriptor(centro_truncate); //libero centro de mensajes con sus datos y conexiones
                return -EAGAIN;

            } else {

                while (! (datos.estado)) {

                    while(! (mtf_recibir_mensajes(centro_truncate)));

                datosMensaje = mtf_siguiente_mensaje(centro_truncate);
                ___fuse_procesar_mensaje_truncate(centro_truncate, datosMensaje, &datos);
                mtf_descartar_mensaje(centro_truncate, datosMensaje.codigo);
                }

            }
                mtf_desconectar(centro_truncate,descriptorConexion); //desconecto la conexion del centro de mensajes
                mtf_liberar_descriptor(centro_truncate); //libero centro de mensajes con sus datos y conexiones

                switch (datos.estado) {

                    case 1:
                        return -ENOENT; //path no existe
                    case 2:
                        return -EISDIR;//archivo es un directorio
                    case 3:
                        return -EACCES; //archivo de solo lectura
                    case 4:
                        return -EFBIG; //la pos de truncar excede el final del archivo
                    default:
                        return EXIT_SUCCESS;
                }
}

void ___fuse_procesar_mensaje_truncate(unsigned char centro_truncate, mti_mensaje datosMensaje, struct datosTruncar * datosTruncados) {


      if (datosMensaje.categoria != MTA_MENSAJE) return;

            switch (datosMensaje.tipo) {


            case MTE_NULL:

                mtf_enviar_mensaje(centro_truncate, datosMensaje.remitente, MTR_NULL);

            break;

            case MTR_NULL:

            break;

            case MTQ_MENSAJE_NO_VALIDO:

            break;

            //MENSAJES PARA TRUNCAR ARCHIVO
            case MTR_ARCHIVO_TRUNCADO:
            {
                char * nombreArchivo = NULL;

                    mtf_obtener_datos(centro_truncate, datosMensaje.codigo, (long long *) &nombreArchivo);

                    log_registrar(descArch, "FUSE",LOG_INFO, "Archivo truncado %s \n", nombreArchivo);
                    free(nombreArchivo);
            }
            break;

            case MTR_ARCHIVO_NO_TRUNCO:
            {
                char * nombreArchivo = NULL;
                char motivo;

                    mtf_obtener_datos(centro_truncate,datosMensaje.codigo, (long long *) &nombreArchivo, (char *)
                                        &motivo);

                    datosTruncados -> estado = motivo;
                    log_registrar(descArch, "FUSE", LOG_WARN, "No se pudo truncar archivo %s \n", nombreArchivo);
                    free(nombreArchivo);
            }
            break;

            default:

                    mtf_enviar_mensaje(centro_truncate, datosMensaje.remitente, MTQ_MENSAJE_NO_VALIDO);

            break;
        }
}

#endif

